package com.zs.netty.jdknio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;

public class MyNioClient {
    private boolean isOver;
    private Selector selector;          //创建一个选择器
    private final static int port = 8686;
    private final static int BUF_SIZE = 10240;
    private static ByteBuffer byteBuffer = ByteBuffer.allocate(BUF_SIZE);

    private void initClient() throws Exception {
        // 获得一个通道管理器
        selector = Selector.open();
        // 获得一个Socket通道
        SocketChannel clientChannel = SocketChannel.open();

        // 设置通道为非阻塞
        clientChannel.configureBlocking(false);
        clientChannel.connect(new InetSocketAddress(port));
        clientChannel.register(selector, SelectionKey.OP_CONNECT);
    }

    /**
     * 采用轮询的方式监听selector上是否有需要处理的事件，如果有，则进行处理
     *
     * @throws Exception
     */
    private void listen() throws Exception {
        isOver = false;
        while (!isOver) {
            selector.select();
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
                if (key.isConnectable()) {
                    doConnect(key);
                } else if (key.isReadable()) {
                    doRead(key);
                }
            }
        }
    }

    private void doConnect(SelectionKey key) throws IOException {
        SocketChannel clientChannel = (SocketChannel) key.channel();
        // 如果正在连接，则完成连接
        if (clientChannel.isConnectionPending()) {
            clientChannel.finishConnect();
        }
        // 设置成非阻塞
        clientChannel.configureBlocking(false);
        //在和服务端连接成功之后，为了可以接收到服务端的信息，需要给通道设置读的权限。
        clientChannel.register(this.selector, SelectionKey.OP_READ);

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入：");
        String info = scanner.nextLine();
        byteBuffer.clear();
        byteBuffer.put(info.getBytes("UTF-8"));
        byteBuffer.flip();
        clientChannel.write(byteBuffer);
    }

    private void doRead(SelectionKey key) throws IOException {
        SocketChannel clientChannel = (SocketChannel) key.channel();
        byteBuffer.clear();
        int read = clientChannel.read(byteBuffer);
        if (read > 0) {
            byteBuffer.flip();
            byte[] data = byteBuffer.array();
            String msg = new String(data).trim();
            System.out.println("服务端发送消息：" + msg);
        } else {
            clientChannel.close();
        }

        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入：");
        String info = scanner.nextLine();
        if (("exit").equals(info)) {
            isOver = true;
        } else {
            byteBuffer.clear();
            byteBuffer.put(info.getBytes("UTF-8"));
            byteBuffer.flip();
            clientChannel.write(byteBuffer);
        }
    }

    public static void main(String[] args) throws Exception {
        MyNioClient myNioClient = new MyNioClient();
        myNioClient.initClient();
        myNioClient.listen();
    }
}